package com.joker.aigc.chat.service.strategy;

import cn.hutool.core.bean.BeanUtil;
import com.joker.aigc.domain.enums.AppHttpCodeEnum;
import com.joker.aigc.chat.dao.RoomDao;
import com.joker.aigc.chat.domain.dto.MessageDto;
import com.joker.aigc.chat.domain.entity.Message;
import com.joker.aigc.chat.domain.entity.Room;
import com.joker.aigc.chat.domain.enums.MessageTypeEnum;
import com.joker.aigc.chat.mapper.MessageMapper;
import com.joker.aigc.chat.service.adapter.MessageAdapter;
import com.joker.aigc.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.lang.reflect.ParameterizedType;

/**
 * Description: 消息处理器抽象类
 * Author: <a href="https://github.com/zongzibinbin">abin</a>
 * Date: 2023-06-04
 */
public abstract class AbstractMsgHandler<Req> {


    @Autowired
    private MessageMapper messageDao;

    @Autowired
    private RoomDao roomDao;

    private Class<Req> bodyClass;

    @PostConstruct
    private void init() {
        // 在初始化的时候。获取谁继承了这个类。
        // 然后把这些继承这个类的信息。注入到 bodyClass中。这样子就可以
        ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.bodyClass = (Class<Req>) genericSuperclass.getActualTypeArguments()[0];
        MsgHandlerFactory.register(getMsgTypeEnum().getType(), this);
    }

    /**
     * 消息类型
     */
    abstract MessageTypeEnum getMsgTypeEnum();

    // 校验 extra 消息
    abstract void checkMessageExtra(Req body, Long roomId, Long uid);

    @Transactional // 校验消息 并且保存消息
    public Message checkAndSaveMsg(MessageDto request, Long uid) {
        Req body = this.toBean(request.getBody());
        // 首先校验 房间号是否存在
        Room room = roomDao.getById(request.getRoomId());
        AssertUtil.isNotEmpty(room, AppHttpCodeEnum.ROOM_NOT_EXIST);
        //统一校验
        AssertUtil.allCheckValidateThrow(body);
        //子类扩展校验
        checkMessageExtra(body, request.getRoomId(), uid);
        Message message = MessageAdapter.buildMsgSave(request, uid);
        //统一保存
        messageDao.insert(message);
        //子类扩展信息的保存
        saveMessageExtra(message, body);
        return message;
    }

    private Req toBean(Object body) {
        if (bodyClass.isAssignableFrom(body.getClass())) {
            return (Req) body;
        }
        return BeanUtil.toBean(body, bodyClass);
    }

    //
    protected abstract void saveMessageExtra(Message message, Req body);

    /**
     * 展示消息
     */
    public abstract Object showMsg(Message msg);

    /**
     * 被回复时——展示的消息
     */
    public abstract Object showReplyMsg(Message msg);

    /**
     * 会话列表——展示的消息
     */
    public abstract String showContactMsg(Message msg);

}
